#include <stdio.h>
#include <stdlib.h>     //exit()
#include <string.h>
#include <errno.h>
#include <fcntl.h>      // 非阻塞宏
#include <sys/ioctl.h>
#include <sys/epoll.h>  // epoll管理服务器的连接和接收触发
#include <sys/socket.h>
#include <netinet/ip.h>
#include <pthread.h>    // 使用多线程
#include "websocket_common.h"

#define _CRT_SECURE_NO_WARNINGS 1
#include <assert.h>

int substr(char dst[], char src[],int start,int len)
{
     char* sc = src+start;
    int n = strlen(sc);
    int i = 0;
    int **ret=NULL;
    assert(dst != NULL );
    assert(src != NULL ); 
    if(n < len)
    {
        len = n;
    }
    while(len)
    {
        dst[i] = sc[i];
        len--;
        i++;
    }
    dst[i] = '\0';
    return i;
}
///////在线列表////////////////
typedef struct {
    int fd;
    char nickname[64];
}Client_item;
#define		line_RESPOND_NUM		10000	// 最大同时管理数量
Client_item onlineClients[line_RESPOND_NUM];
int clientCount;

void addClient(int fd,char *name)
{
    int i=0;
    int f=0;
    for(;i<clientCount;i++)
    {
        if(onlineClients[i].fd==fd)
        {
            int l=strlen(name);
            if (l>63)
                l=63;
            memset(onlineClients[i].nickname,0,64);
            strncpy(onlineClients[i].nickname,name,l);
            f=1;
            break;
        }
    }
    if(!f){
    onlineClients[clientCount].fd=fd;
    int l=strlen(name);
    if (l>63)
        l=63;
    memset(onlineClients[clientCount].nickname,0,64);
    strncpy(onlineClients[clientCount].nickname,name,l);
    clientCount++;
    }
}
/*****************************************
 * 获取客户昵称
 * 参数：fd句柄
 * 返回：没有NULL 
 * ****************************************/
char* getClient_nickname(int fd)
{
    int i=0;
    int f=0;
    for(;i<clientCount;i++)
    {
        if(onlineClients[i].fd==fd)
        {            
            f=1;
            break;
        }
    }
    if(f)
    {
        return onlineClients[i].nickname;
    }
    else
    return NULL;
}
int getClient_fd(char *name)
{
    int i=0;
    int f=0;
    for(;i<clientCount;i++)
    {
        if((strstr(onlineClients[i].nickname,name))&&(strlen(onlineClients[i].nickname)==strlen(name)))
        {            
            f=1;
            break;
        }
    }
    if(f)
    {
        return onlineClients[i].fd;
    }
    else
    return 0;
}
void delClient(int fd)
{
    int f=0;
    int i;
    for(i=clientCount;i>=0;i--)
    {
        if(fd==onlineClients[i].fd)
        {
            f=1;
            printf("用户:%s,退出..\r\n",onlineClients[i].nickname);
            break;
        }
    }
    if(f){
        int j=i;
    for( j=i;j<clientCount;j++)
    {
        if((j+1)<=clientCount)
        {
            onlineClients[j].fd =onlineClients[j+1].fd;
            memset(onlineClients[j].nickname,0,64);
            strcpy(onlineClients[j].nickname,onlineClients[j+1].nickname);
        }
    }
    clientCount--;
    }
}
/******************************************
 * 响应客户端
 * 参数： fd 句柄
 *       datatype 数据类型
 *       buf 缓存
 *       bufLen 缓存大小
 * 说明：数据接收数据后，请在此对数据进行处理。
******************************************/
int server_callBack(int fd,WebsocketData_Type datatype, char *buf, unsigned int bufLen)
{
    int ret;
    if(bufLen > 0)
	{
        /*
		printf("server(fd/%d) recv:\r\n"
            "\t数据类型：%d\r\n"
            "\t数据长度byte:%d\r\n"
            "\t内容：%s\r\n"
            , fd,datatype,bufLen, buf);	
            */
		//===== 在这里根据客户端的请求内容, 提供相应的服务 =====
        if(datatype==WDT_DISCONN)
        {
            int delfd=fd;
            delClient(delfd);
            printf("在线成员有%d个.\n",clientCount);

        }
		else if(strstr(buf, "hi~") != NULL)
		    ret = webSocket_send(fd, "Hi~ I am server", strlen("Hi~ I am server"), false, WDT_TXTDATA);
		else if((strstr(buf,"join:")!=NULL)&&(strstr(buf,"join:")==buf))
        {
            char nickname[64]={0};  
            int l=strlen(buf)-5;
            if(l>63)
                l=63;
            ret=substr(nickname,buf,5,l);            
            ret = webSocket_send(fd,"欢迎你的到来...",strlen("欢迎你的到来..."),false,WDT_TXTDATA);            
            addClient(fd,nickname); 
            printf("“%s”加入,在线成员有%d个.\r\n",nickname,clientCount);   
        }
        else if((strstr(buf,"to:")!=NULL)&&(strstr(buf,"to:")==buf))
        {
            char nickname[64]={0};
            char *ep=strstr(buf,";");
            if(ep!=NULL){
                int l=ep-buf;
                l-=3;
                if(l>63)
                    l=63;
                ret=substr(nickname,buf,3,l);     
                int tofd=getClient_fd(nickname);
                if(tofd>0){
                    char *fname=getClient_nickname(fd);
                    if(fname!=NULL){
                    unsigned char *recvBuf = NULL;
                    int recvLen=bufLen+strlen(fname)+6;
                    recvBuf = (unsigned char *)calloc(recvLen, sizeof(char));
                    sprintf(recvBuf,"from:%s%s",fname,ep);
                    ret = webSocket_send(tofd,recvBuf,strlen(recvBuf),false,WDT_TXTDATA); 
                    printf("fd:%d,%s 发消息fd:%d,nickname:%s\t%s\r\n",fd,fname,tofd,nickname,recvBuf); 
                    if(recvBuf) free(recvBuf);
                }      
                }      
              
            }
        }
        else if((strstr(buf,"toall")!=NULL)&&(strstr(buf,"toall")==buf))
        {
            char *fname=getClient_nickname(fd);
            if(fname!=NULL){
            char *ep=strstr(buf,";");
            if(ep!=NULL){
                char *sendBuf=NULL;
                int sendLen=bufLen+strlen(fname)+6;
                sendBuf = (char *)calloc(sendLen, sizeof(char));
                sprintf(sendBuf,"from:%s%s",fname,ep);
                for(int i=0;i<clientCount;i++)
                {
                if(fd!=onlineClients[i].fd)
                    ret=webSocket_send(onlineClients[i].fd,sendBuf,strlen(sendBuf),false,WDT_TXTDATA);
                }
                if(sendBuf) free(sendBuf);
            }

            }
        }
        else if((strstr(buf,"getusers;")!=NULL)&&(strstr(buf,"getusers;")==buf))
        {
            char sBuf[10240]={0};
            char *fname=getClient_nickname(fd);
            if(fname!=NULL){
                int j=0;
            for(int i=0;i<clientCount;i++)
            {                
                char val[128];
                sprintf(val,"\tserver fd:%d,nickname:%s",onlineClients[i].fd,onlineClients[i].nickname);
                strcat(sBuf,val);
                if(j>5)
                {
                    j=0;
                    strcat(sBuf,"\r\n");
                }
            }
                ret=webSocket_send(fd,sBuf,strlen(sBuf),false,WDT_TXTDATA);
            }
        }
            ;

           
	}

	return ret;
}
int server_callCloseed(int fd)
{
    printf("server fd %d 关闭。\r\n",fd);
    delClient(fd);
    return 0;
}

int main(void)
{
    memset(&onlineClients,0,line_RESPOND_NUM);
    clientCount=0;
   int ret= server_init(9753,(CallBackFun*)&server_callBack,(CallCloseedFun*)&server_callCloseed);    
    return ret;
//pthread_exit(ret);
}







